package com.example.performance.executor;

import com.example.performance.model.HttpRequest;
import com.example.performance.model.RequestResult;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.*;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Map;

/**
 * HTTP请求执行器
 * 负责执行单个HTTP请求并返回结果
 */
public class HttpRequestExecutor {

    private static final Logger logger = LoggerFactory.getLogger(HttpRequestExecutor.class);

    private final CloseableHttpClient httpClient;

    /**
     * 构造函数，创建HTTP客户端
     */
    public HttpRequestExecutor() {
        // 配置HTTP客户端
        RequestConfig defaultRequestConfig = RequestConfig.custom()
                .setConnectTimeout(30000) // 连接超时30秒
                .setSocketTimeout(30000) // 读取超时30秒
                .setConnectionRequestTimeout(30000) // 从连接池获取连接超时30秒
                .build();

        this.httpClient = HttpClients.custom()
                .setDefaultRequestConfig(defaultRequestConfig)
                .setMaxConnTotal(200) // 最大连接数
                .setMaxConnPerRoute(100) // 每个路由最大连接数
                .build();
    }

    /**
     * 执行HTTP请求
     * 
     * @param request HTTP请求配置
     * @return 请求执行结果
     */
    public RequestResult execute(HttpRequest request) {
        return execute(request, null);
    }

    /**
     * 执行HTTP请求，支持全局请求头
     * 
     * @param request       HTTP请求配置
     * @param globalHeaders 全局请求头
     * @return 请求执行结果
     */
    public RequestResult execute(HttpRequest request, Map<String, String> globalHeaders) {
        RequestResult result = new RequestResult(request.getName(), request.getUrl(), request.getMethod());
        result.setStartTime(System.currentTimeMillis());

        try {
            // 创建HTTP请求对象
            HttpUriRequest httpRequest = createHttpRequest(request);

            // 设置请求头
            setHeaders(httpRequest, request, globalHeaders);

            // 设置请求体（如果有）
            setRequestBody(httpRequest, request);

            // 执行请求
            logger.debug("执行HTTP请求: {} {}", request.getMethod(), request.getUrl());
            HttpResponse response = httpClient.execute(httpRequest);

            // 处理响应
            handleResponse(response, result, request);

        } catch (Exception e) {
            logger.error("执行HTTP请求失败: {} {}", request.getMethod(), request.getUrl(), e);
            result.markFailure("请求执行异常: " + e.getMessage());
        }

        return result;
    }

    /**
     * 创建HTTP请求对象
     * 
     * @param request HTTP请求配置
     * @return HTTP请求对象
     */
    private HttpUriRequest createHttpRequest(HttpRequest request) {
        String method = request.getMethod().toUpperCase();
        String url = request.getUrl();

        // 设置请求超时
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectTimeout(request.getTimeout())
                .setSocketTimeout(request.getTimeout())
                .setConnectionRequestTimeout(request.getTimeout())
                .build();

        HttpUriRequest httpRequest;

        switch (method) {
            case "GET":
                HttpGet getRequest = new HttpGet(url);
                getRequest.setConfig(requestConfig);
                httpRequest = getRequest;
                break;
            case "POST":
                HttpPost postRequest = new HttpPost(url);
                postRequest.setConfig(requestConfig);
                httpRequest = postRequest;
                break;
            case "PUT":
                HttpPut putRequest = new HttpPut(url);
                putRequest.setConfig(requestConfig);
                httpRequest = putRequest;
                break;
            case "DELETE":
                HttpDelete deleteRequest = new HttpDelete(url);
                deleteRequest.setConfig(requestConfig);
                httpRequest = deleteRequest;
                break;
            case "HEAD":
                HttpHead headRequest = new HttpHead(url);
                headRequest.setConfig(requestConfig);
                httpRequest = headRequest;
                break;
            case "OPTIONS":
                HttpOptions optionsRequest = new HttpOptions(url);
                optionsRequest.setConfig(requestConfig);
                httpRequest = optionsRequest;
                break;
            case "PATCH":
                HttpPatch patchRequest = new HttpPatch(url);
                patchRequest.setConfig(requestConfig);
                httpRequest = patchRequest;
                break;
            default:
                throw new IllegalArgumentException("不支持的HTTP方法: " + method);
        }

        // 注意：在Apache HttpClient 4.5中，RequestConfig需要在创建请求时设置
        // 这里我们将配置应用到每个具体的请求类型
        if (httpRequest instanceof RequestBuilder) {
            // 对于使用RequestBuilder创建的请求
        } else {
            // 对于直接创建的请求，配置已经在创建时设置
        }
        return httpRequest;
    }

    /**
     * 设置请求头
     * 
     * @param httpRequest   HTTP请求对象
     * @param request       HTTP请求配置
     * @param globalHeaders 全局请求头
     */
    private void setHeaders(HttpUriRequest httpRequest, HttpRequest request, Map<String, String> globalHeaders) {
        // 设置全局请求头
        if (globalHeaders != null && !globalHeaders.isEmpty()) {
            for (Map.Entry<String, String> entry : globalHeaders.entrySet()) {
                httpRequest.setHeader(entry.getKey(), entry.getValue());
            }
        }

        // 设置请求特定的请求头（会覆盖全局请求头）
        if (request.getHeaders() != null && !request.getHeaders().isEmpty()) {
            for (Map.Entry<String, String> entry : request.getHeaders().entrySet()) {
                httpRequest.setHeader(entry.getKey(), entry.getValue());
            }
        }

        // 如果没有设置Content-Type且有请求体，设置默认Content-Type
        if (request.getBody() != null && !request.getBody().isEmpty()) {
            if (httpRequest.getFirstHeader("Content-Type") == null) {
                httpRequest.setHeader("Content-Type", "application/json; charset=UTF-8");
            }
        }
    }

    /**
     * 设置请求体
     * 
     * @param httpRequest HTTP请求对象
     * @param request     HTTP请求配置
     */
    private void setRequestBody(HttpUriRequest httpRequest, HttpRequest request) throws IOException {
        if (request.getBody() != null && !request.getBody().isEmpty()) {
            if (httpRequest instanceof HttpEntityEnclosingRequestBase) {
                HttpEntityEnclosingRequestBase entityRequest = (HttpEntityEnclosingRequestBase) httpRequest;
                StringEntity entity = new StringEntity(request.getBody(), StandardCharsets.UTF_8);
                entityRequest.setEntity(entity);
            } else {
                logger.warn("HTTP方法 {} 不支持请求体，忽略body参数", request.getMethod());
            }
        }
    }

    /**
     * 处理HTTP响应
     * 
     * @param response HTTP响应
     * @param result   结果对象
     * @param request  请求配置
     */
    private void handleResponse(HttpResponse response, RequestResult result, HttpRequest request) throws IOException {
        int statusCode = response.getStatusLine().getStatusCode();

        // 读取响应体
        String responseBody = "";
        HttpEntity entity = response.getEntity();
        if (entity != null) {
            try {
                responseBody = EntityUtils.toString(entity, StandardCharsets.UTF_8);
            } finally {
                EntityUtils.consume(entity); // 确保连接释放
            }
        }

        // 判断请求是否成功
        boolean isSuccess = (statusCode == request.getExpectedStatusCode()) ||
                (request.getExpectedStatusCode() == 200 && statusCode >= 200 && statusCode < 300);

        if (isSuccess) {
            result.markSuccess(statusCode, responseBody);
            logger.debug("请求成功: {} {} - 状态码: {}, 响应时间: {}ms",
                    request.getMethod(), request.getUrl(), statusCode, result.getResponseTime());
        } else {
            result.markFailure(statusCode, "意外的状态码: " + statusCode + ", 期望: " + request.getExpectedStatusCode());
            logger.warn("请求失败: {} {} - 状态码: {}, 期望: {}",
                    request.getMethod(), request.getUrl(), statusCode, request.getExpectedStatusCode());
        }
    }

    /**
     * 关闭HTTP客户端，释放资源
     */
    public void close() {
        try {
            if (httpClient != null) {
                httpClient.close();
            }
        } catch (IOException e) {
            logger.error("关闭HTTP客户端失败", e);
        }
    }

    /**
     * 检查HTTP客户端是否健康
     * 
     * @return 是否健康
     */
    public boolean isHealthy() {
        // 简单的健康检查，实际应用中可以添加更多检查逻辑
        return httpClient != null;
    }
}